package com.queclink.puzzle.common;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author jim.li
 * @email jim.li@queclink.com
 * @date 2022-06-16 17:21:00
 */
@Async
@Component
public class Solution {

    private static final String initial_label_text = "00:00:00 000";

    private countingthread thread = new countingthread();
    // 记录程序开始时间
    private long programstart = System.currentTimeMillis();

    // 程序一开始就是暂停的
    private long pausestart = programstart;
    // 程序暂停的总时间
    private long pausecount = 0;

    private class countingthread extends Thread {

        public boolean stopped = true;

        private countingthread() {
            setDaemon(true);
        }

        @Override
        public void run() {

            while (!stopped) {

//                if (!stopped) {
                    long elapsed = System.currentTimeMillis() - programstart - pausecount;
                    label.setText(format(elapsed));
//                }
                try {
                    Thread.sleep(1); // 1毫秒更新一次显示
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }

        // 将毫秒数格式化
        private String format(long elapsed) {
            int hour, minute, second, milli;
            milli = (int) (elapsed % 1000);
            elapsed = elapsed / 1000;
            second = (int) (elapsed % 60);
            elapsed = elapsed / 60;
            minute = (int) (elapsed % 60);
            elapsed = elapsed / 60;
            hour = (int) (elapsed % 60);
            return String.format("%02d:%02d:%02d %03d", hour, minute, second, milli);

        }

    }

    private JLabel label = new JLabel(initial_label_text);


    public static final int[][] A_three_l = {
            {1, 0},
            {1, 1}};

    public static final int[][] B_four_square = {
            {2, 2},
            {2, 2}};

    public static final int[][] C_four_convex = {
            {0, 3, 0},
            {3, 3, 3}};

    public static final int[][] D_four_l = {
            {4, 0},
            {4, 0},
            {4, 4}};

    public static final int[][] E_four_line = {
            {5, 5, 5, 5}};

    public static final int[][] F_four_z = {
            {6, 6, 0},
            {0, 6, 6}};

    public static final int[][] G_five_l = {
            {7, 0},
            {7, 0},
            {7, 0},
            {7, 7}};

    public static final int[][] H_five_square = {
            {8, 0},
            {8, 8},
            {8, 8}};

    public static final int[][] I_five_convex = {
            {0, 0, 9, 0},
            {9, 9, 9, 9}};

    public static final int[][] J_five_concave = {
            {10, 0, 10},
            {10, 10, 10}};

    public static final int[][] K_five_v = {
            {11, 0, 0},
            {11, 0, 0},
            {11, 11, 11}};

    public static final int[][] WEEK = {{0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}, {1, 2}, {1, 3}};
    public static final int[][] MONTH = {{0, 4}, {0, 5}, {0, 6}, {1, 7},
            {1, 4}, {1, 5}, {1, 6}, {1, 7},
            {2, 4}, {2, 5}, {2, 6}, {2, 7}};
    public static final int[][] DAY = {{2, 0}, {2, 1}, {2, 2}, {2, 3},
            {3, 0}, {3, 1}, {3, 2}, {3, 3}, {3, 4}, {3, 5}, {3, 6}, {3, 7},
            {4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}, {4, 5}, {4, 6}, {4, 7},
            {5, 0}, {5, 1}, {5, 2}, {5, 3}, {5, 4}, {5, 5}, {5, 6}, {5, 7},
            {6, 0}, {6, 1}, {6, 2},};
    public static int[][] map = {
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 99, 99, 99, 99, 99}};

    public static final List<int[][]> puzzleList = new ArrayList<int[][]>() {{
        add(A_three_l);
        add(B_four_square);
        add(C_four_convex);
        add(D_four_l);
        add(E_four_line);
        add(F_four_z);
        add(G_five_l);
        add(H_five_square);
        add(I_five_convex);
        add(J_five_concave);
        add(K_five_v);
    }};

    // 顺时针旋转90度
    public static int[][] clockWise(int[][] puzzle) {
        int m = puzzle.length;
        int n = puzzle[0].length;
        //m表示原数组的行，n表示原数组的列
        int arry2[][] = new int[n][m];
        int dst;
        dst = m - 1;//因为要从最后一列向前赋值
        for (int x = 0; x < m; x++, dst--) {
            for (int y = 0; y < n; y++) {
                arry2[y][dst] = puzzle[x][y];
//在内循环中保持列不变，实现一列一列的赋值，同时也是从最后一列向前赋值
            }
        }
        return arry2;
    }

    // 逆时针旋转90度
    public static int[][] antiClockWise(int[][] puzzle) {
        int m = puzzle.length;
        int n = puzzle[0].length;
        int dst;
        int arry3[][] = new int[n][m];
        for (int x = 0; x < m; x++) {
            dst = n -1;//因为要从最后一行向前赋值
            for (int y = 0; y < n ; y++,dst--) {
                arry3[dst][x] = puzzle[x][y];
//在内循环中保持列不变，实现一列一列的赋值，同时也是从最后一行向前赋值
            }
        }
        return arry3;
    }

    // 对称翻转
    public static int[][] reverse(int[][] puzzle) {
        int m = puzzle.length;
        int n = puzzle[0].length;
        int arry2[][] = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                arry2[i][n - 1 - j] = puzzle[i][j];
            }
        }
        return arry2;
    }

    // 顺时针旋转1800度
    public static int[][] antiClockWise180(int[][] puzzle) {
        int m = puzzle.length;
        int n = puzzle[0].length;
        int arry4[][] = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                arry4[i][j] = puzzle[m - 1 - i][n - 1 - j];
            }
        }
        return arry4;
    }

    public static int[][] flipPuzzle(int[][] puzzle, int direction) {
        if (direction == 0) {
            return puzzle;
        } else if (direction == 1) {
            // 旋转90度
            return clockWise(puzzle);
        } else if (direction == 2) {
            // 旋转180度
            return antiClockWise180(puzzle);
        } else if (direction == 3) {
            // 逆时针90度
            return antiClockWise(puzzle);
        }  else if (direction == 4) {
            // 反
            return reverse(puzzle);
        } else if (direction == 5) {
            // 旋转90度，反
            int[][] puzzle1 = clockWise(puzzle);
            return reverse(puzzle1);
        } else if (direction == 6) {
            // 旋转180度，反
            int[][] puzzle2 = antiClockWise180(puzzle);
            return reverse(puzzle2);
        } else {
            // 逆时针90度，反
            int[][] puzzle3 = antiClockWise(puzzle);
            return reverse(puzzle3);
        }
    }

    // 获取当前位置
    public static int[] getPosition(int position) {
        int x = position / 8;
        int y = position % 8;
        return new int[]{x, y};
    }

    public static void deepCopy(int[][] sourceArr, int[][] destArr) {
        for (int i = 0; i < sourceArr.length; i++) {
            destArr[i] = Arrays.copyOf(sourceArr[i], sourceArr[i].length);
        }
    }

    // 判断当前位置是否能放拼图
    public static boolean putPuzzle(int[][] puzzle, int[][] map, int count, int direction, int position) {
        int[][] newPuzzle = flipPuzzle(puzzle, direction);
        int puzzleRow = newPuzzle.length;
        int puzzleColumn = newPuzzle[0].length;
        int[] currentPosition = getPosition(position);
        int x = currentPosition[0];
        int y = currentPosition[1];
        int[][] newMap = new int[7][8];
        deepCopy(map, newMap);
        for (int i = 0; i < puzzleRow; i++) {
            for (int j = 0; j < puzzleColumn; j++) {
                if (x + i > 6 || y + j > 7) {
                    return false;
                }
                if (map[x + i][y + j] != 0 && newPuzzle[i][j] != 0) {
                    return false;
                }
                if (newPuzzle[i][j] != 0) {
                    newMap[x + i][y + j] = newPuzzle[i][j];
                }
            }
        }
        // 检查一下上、左、右 三边是否存在空一个
        for (int i = 0; i < newMap[0].length; i++) {
            if (newMap[0][i] == 0 && newMap[1][i] != 0) {
                if (i == 0 && newMap[0][i + 1] != 0) {
                    return false;
                }
                if (i == 7 && newMap[0][i - 1] != 0) {
                    return false;
                }
                if (i > 0 && i < 7 && newMap[0][i - 1] != 0 && newMap[0][i + 1] != 0) {
                    return false;
                }
            }
        }
        for (int i = 1; i < newMap.length; i++) {
            if (newMap[i][0] == 0 && newMap[i - 1][0] != 0 && newMap[i][1] != 0) {
                if (i < 6 && newMap[i + 1][0] != 0) {
                    return false;
                }
            }
        }
        for (int i = 1; i < newMap.length - 1; i++) {
            if (newMap[i][7] == 0 && newMap[i - 1][7] != 0 && newMap[i][6] != 0) {
                if (i < 5 && newMap[i + 1][7] != 0) {
                    return false;
                }
            }
        }
        deepCopy(newMap, map);
        return true;
    }

    public static int getFirstPositionMap(int[][] map) {
        int position = 0;
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length; j++) {
                if (map[i][j] == 0) {
                    position = i * 8 + j;
                    return position;
                }
            }
        }
        return position;
    }


    @Async
    public int[][] solution(int month, int day, int week) {
        int[] month_occupy = MONTH[month - 1];
        int[] day_occupy = DAY[day - 1];
        int[] week_occupy = WEEK[week - 1];
        map[month_occupy[0]][month_occupy[1]] = 30;
        map[day_occupy[0]][day_occupy[1]] = 66;
        map[week_occupy[0]][week_occupy[1]] = 77;

        int size;
        int[][] newMap = new int[7][8];
        deepCopy(map, newMap);
        // 第一块
        for (int d1 = 0; d1 < 4; d1++) {
            int count1 = 0;
            for (int p1 = 0; p1 < 48; p1++) {
                // 暂存地图
                int[][] newMap1 = new int[7][8];
                deepCopy(newMap, newMap1);
                int sum = 0;
                size = 0;
                int[][] puzzle = puzzleList.get(size);
                boolean ret = putPuzzle(puzzle, newMap1, size, d1, p1);
                if (!ret) {
                    if (p1 == 46 && count1 != 0) {
                        sum--;
                    }
                    continue;
                } else {
                    if (count1 == 0) {
                        sum++;
                    }
                    count1 ++;
                }

                int positionMap2 = getFirstPositionMap(newMap1);

                // 第二块
                for (int d2 = 0; d2 < 1; d2++) {
                    int count2 = 0;
                    for (int p2 = positionMap2; p2 < 48; p2++) {
                        // 暂存拼图
                        int[][] newMap2 = new int[7][8];
                        deepCopy(newMap1, newMap2);
                        size = 1;
                        puzzle = puzzleList.get(size);
                        ret = putPuzzle(puzzle, newMap2, size, d2, p2);
                        if (!ret) {
                            if (p2 == 46 && count2 != 0) {
                                sum--;
                            }
                            continue;
                        } else {
                            if (count2 == 0) {
                                sum++;
                            }
                            count2++;
                        }
                        int positionMap3 = getFirstPositionMap(newMap2);
                        // 第三块
                        for (int d3 = 0; d3 < 4; d3++) {
                            int count3 = 0;
                            for (int p3 = positionMap3; p3 < 48; p3++) {
//                                int count3 = 0;
                                // 暂存拼图
                                int[][] newMap3 = new int[7][8];
                                deepCopy(newMap2, newMap3);
                                size = 2;
                                puzzle = puzzleList.get(size);
                                ret = putPuzzle(puzzle, newMap3, size, d3, p3);
                                if (!ret) {
                                    if (p3 == 46 && count3 != 0) {
                                        sum--;
                                    }
                                    continue;
                                } else {
                                    if (count3 == 0) {
                                        sum++;
                                    }
                                    count3++;
                                }

                                int positionMap4 = getFirstPositionMap(newMap3);
                                // 第四块
                                for (int d4 = 0; d4 < 8; d4++) {
                                    int count4 = 0;
                                    for (int p4 = positionMap4; p4 < 48; p4++) {
//                                        int count4 = 0;
                                        // 暂存拼图
                                        int[][] newMap4 = new int[7][8];
                                        deepCopy(newMap3, newMap4);
                                        size = 3;
                                        puzzle = puzzleList.get(size);
                                        ret = putPuzzle(puzzle, newMap4, size, d4, p4);
                                        if (!ret) {
                                            if (p4 == 46 && count4 != 0) {
                                                sum--;
                                            }
                                            continue;
                                        } else {
                                            if (count4 == 0) {
                                                sum++;
                                            }
                                            count4++;
                                        }

                                        int positionMap5 = getFirstPositionMap(newMap4);
                                        // 第五块
                                        for (int d5 = 0; d5 < 2; d5++) {
                                            int count5 = 0;
                                            for (int p5 = positionMap5; p5 < 48; p5++) {
//                                                int count5 = 0;
                                                // 暂存拼图
                                                int[][] newMap5 = new int[7][8];
                                                deepCopy(newMap4, newMap5);
                                                size = 4;
                                                puzzle = puzzleList.get(size);
                                                ret = putPuzzle(puzzle, newMap5, size, d5, p5);
                                                if (!ret) {
                                                    if (p5 == 46 && count5 != 0) {
                                                        sum--;
                                                    }
                                                    continue;
                                                } else {
                                                    if (count5 == 0) {
                                                        sum++;
                                                    }
                                                    count5++;
                                                }

                                                int positionMap6 = getFirstPositionMap(newMap5);
                                                // 第六块
                                                for (int d6 = 2; d6 < 6; d6++) {
                                                    int count6 = 0;
                                                    for (int p6 = positionMap6; p6 < 48; p6++) {
                                                        // 暂存拼图
                                                        int[][] newMap6 = new int[7][8];
                                                        deepCopy(newMap5, newMap6);
                                                        size = 5;
                                                        puzzle = puzzleList.get(size);
                                                        ret = putPuzzle(puzzle, newMap6, size, d6, p6);
                                                        if (!ret) {
                                                            if (p6 == 46 && count6 != 0) {
                                                                sum--;
                                                            }
                                                            continue;
                                                        } else {
                                                            if (count6 == 0) {
                                                                sum++;
                                                            }
                                                            count6++;
                                                        }

                                                        int positionMap7 = getFirstPositionMap(newMap6);
                                                        // 第七块
                                                        for (int d7 = 0; d7 < 8; d7++) {
                                                            int count7 = 0;
                                                            for (int p7 = positionMap7; p7 < 48; p7++) {
                                                                // 暂存拼图
                                                                int[][] newMap7 = new int[7][8];
                                                                deepCopy(newMap6, newMap7);
                                                                size = 6;
                                                                puzzle = puzzleList.get(size);
                                                                ret = putPuzzle(puzzle, newMap7, size, d7, p7);
                                                                if (!ret) {
                                                                    if (p7 == 46 && count7 != 0) {
                                                                        sum--;
                                                                    }
                                                                    continue;
                                                                } else {
                                                                    if (count7 == 0) {
                                                                        sum++;
                                                                    }
                                                                    count7++;
                                                                }

                                                                int positionMap8 = getFirstPositionMap(newMap7);
                                                                // 第八块
                                                                for (int d8 = 0; d8 < 8; d8++) {
                                                                    int count8 = 0;
                                                                    for (int p8 = positionMap8; p8 < 48; p8++) {
                                                                        // 暂存拼图
                                                                        int[][] newMap8 = new int[7][8];
                                                                        deepCopy(newMap7, newMap8);
                                                                        size = 7;
                                                                        puzzle = puzzleList.get(size);
                                                                        ret = putPuzzle(puzzle, newMap8, size, d8, p8);
                                                                        if (!ret) {
                                                                            if (p8 == 46 && count8 != 0) {
                                                                                sum--;
                                                                            }
                                                                            continue;
                                                                        } else {
                                                                            if (count8 == 0) {
                                                                                sum++;
                                                                            }
                                                                            count8++;
                                                                        }

                                                                        int positionMap9 = getFirstPositionMap(newMap8);
                                                                        // 第九块
                                                                        for (int d9 = 0; d9 < 8; d9++) {
                                                                            int count9 = 0;
                                                                            for (int p9 = positionMap9; p9 < 48; p9++) {
                                                                                // 暂存拼图
                                                                                int[][] newMap9 = new int[7][8];
                                                                                deepCopy(newMap8, newMap9);
                                                                                size = 8;
                                                                                puzzle = puzzleList.get(size);
                                                                                ret = putPuzzle(puzzle, newMap9, size, d9, p9);
                                                                                if (!ret) {
                                                                                    if (p9 == 46 && count9 != 0) {
                                                                                        sum--;
                                                                                    }
                                                                                    continue;
                                                                                } else {
                                                                                    if (count9 == 0) {
                                                                                        sum++;
                                                                                    }
                                                                                    count9++;
                                                                                }

                                                                                int positionMap10 = getFirstPositionMap(newMap9);
                                                                                // 第十块
                                                                                for (int d10 = 0; d10 < 4; d10++) {
                                                                                    int count10 = 0;
                                                                                    for (int p10 = positionMap10; p10 < 48; p10++) {
                                                                                        // 暂存拼图
                                                                                        int[][] newMap10 = new int[7][8];
                                                                                        deepCopy(newMap9, newMap10);
                                                                                        size = 9;
                                                                                        puzzle = puzzleList.get(size);
                                                                                        ret = putPuzzle(puzzle, newMap10, size, d10, p10);
                                                                                        if (!ret) {
                                                                                            if (p10 == 46 && count10 != 0) {
                                                                                                sum--;
                                                                                            }
                                                                                            continue;
                                                                                        } else {
                                                                                            if (count10 == 0) {
                                                                                                sum++;
                                                                                            }
                                                                                            count10++;
                                                                                        }

                                                                                        int positionMap11 = getFirstPositionMap(newMap10);
                                                                                        // 第十一块
                                                                                        for (int d11 = 0; d11 < 4; d11++) {
                                                                                            int count11 = 0;
                                                                                            for (int p11 = positionMap11; p11 < 48; p11++) {
                                                                                                // 暂存拼图
                                                                                                int[][] newMap11 = new int[7][8];
                                                                                                deepCopy(newMap10, newMap11);
                                                                                                size = 10;
                                                                                                puzzle = puzzleList.get(size);
                                                                                                ret = putPuzzle(puzzle, newMap11, size, d11, p11);
                                                                                                // 如果最后一块放不进去
                                                                                                if (ret) {
                                                                                                    System.out.println("第一个拼图方向：" +  d1 + "。第一个拼图位置：" + p1 + "。当前时间：" + new Date());
                                                                                                    if (count11 == 0) {
                                                                                                        sum++;
                                                                                                    }
                                                                                                    count11++;
                                                                                                    if (sum == 11) {
                                                                                                        Place.stopped = true;
                                                                                                        Place.startButton.setText("开始");
                                                                                                        PuzzlePanel.map = newMap11;
                                                                                                        PuzzleJFrame.openNewJFrame();
                                                                                                        return newMap11;
                                                                                                    }
                                                                                                } else {
                                                                                                    if (p11 == 46 && count11 != 0) {
                                                                                                        sum--;
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        System.out.println("未拼出来");
        return newMap;
    }
}
